package com.cloudkinto.service.platform.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.bo.order.allocate.AllocatePlanProductQueryBo;
import com.cloudkinto.bo.stock.ProductStockBySkuQueryBo;
import com.cloudkinto.common.RabbitQueueConstant;
import com.cloudkinto.common.RedisKeyConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.utils.MathUtils;
import com.cloudkinto.common.utils.StringsUtil;
import com.cloudkinto.common.utils.TimeUtils;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.AllocatePlanDao;
import com.cloudkinto.dao.PlatformProductDao;
import com.cloudkinto.dao.PlatformProductMappingDao;
import com.cloudkinto.dao.ProductDao;
import com.cloudkinto.dto.platform.product.PlatformProductDto;
import com.cloudkinto.dto.platform.product.PlatformProductExportVo;
import com.cloudkinto.dto.platform.product.PlatformProductMappingDto;
import com.cloudkinto.dto.platform.product.ProductSysDto;
import com.cloudkinto.dto.product.PlatformProductBatchInsertReq;
import com.cloudkinto.dto.stock.query.SkuStockPageDto;
import com.cloudkinto.entity.*;
import com.cloudkinto.enumType.common.CountryEnum;
import com.cloudkinto.enumType.operate.OperateTypeEnum;
import com.cloudkinto.service.consumer.vo.amazon.AmazonItemConsumerReq;
import com.cloudkinto.service.consumer.vo.order.UpdateInventoryLessReq;
import com.cloudkinto.service.consumer.vo.rakuten.ItemUpdateConsumerReq;
import com.cloudkinto.service.consumer.vo.yahoo.YahooGetItemReq;
import com.cloudkinto.service.operate.OperateRecordService;
import com.cloudkinto.service.order.allocate.AllocatePlanItemService;
import com.cloudkinto.service.order.allocate.AllocatePlanService;
import com.cloudkinto.service.platform.PlatformProductService;
import com.cloudkinto.service.platform.PlatformStoreService;
import com.cloudkinto.service.platform.vo.order.PlatformOrderImportTrackNoVo;
import com.cloudkinto.service.platform.vo.product.*;
import com.cloudkinto.service.platform.vo.store.PlatformStoreRes;
import com.cloudkinto.service.stock.ProductStockService;
import com.cloudkinto.service.stock.vo.snap.ProductWeightReq;
import com.cloudkinto.utils.BeanChangeUtils;
import com.cloudkinto.vo.channel.lc.LcChannelPageRes;
import com.cloudkinto.vo.order.allocate.AllocateProductListVo;
import com.cloudkinto.vo.product.ProductSkuVo;
import com.cloudkinto.vo.sc.ErrorInfo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author hua
 * @since 2025-01-02
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)//事务回滚
public class PlatformProductServiceImpl extends ServiceImpl<PlatformProductDao, PlatformProductDo> implements PlatformProductService {
    private final PlatformProductDao dao;
    private final PlatformProductMappingDao platformProductMappingDao;
    private final PlatformStoreService storeService;
    private final ProductDao productDao;
    private final RabbitTemplate rabbitTemplate;
    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;
    @Value("${gbc.uploadPath.fileUrlTemp}")
    private String fileUrlTemp;
    @Value("${gbc.uploadPath.filePath}")
    private String filePath;
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;
    private final ProductStockService productStockService;
    private final AllocatePlanItemService allocatePlanItemService;
    private final AllocatePlanDao allocatePlanDao;
    private final OperateRecordService operateRecordService;
    @Value("${gbc.customer}")
    private String customer;
    private final RedisTemplate redisTemplate;


    @Override
    public void updateInventoryLess(UpdateInventoryLessReq req) {
        if (req.getUserId() != null) {
            return;
        }
        Map<Long, Integer> small20IdToQuantityMap = req.getSmall20IdToQuantityMap();
        if (small20IdToQuantityMap == null) {
            return;
        }
        String small20RedisKey = RedisKeyConstants.PLATFORM_STOCK_SMALL20_KEY_PREFIX + customer + "_" + req.getStoreId();
        // 1. 获取上一次缓存的低库存SKU集合（ZSet的member为SKU ID）
        Set<Object> lastSmall20SetTempObj = redisTemplate.opsForZSet().range(small20RedisKey, 0, -1);
        Set<Long> lastSmall20Set = new HashSet<>();
        if (lastSmall20SetTempObj != null) {
            for (Object obj : lastSmall20SetTempObj) {
                // 先转为Number，再获取longValue()，避免直接强转
                if (obj instanceof Number) {
                    lastSmall20Set.add(((Number) obj).longValue());
                }
            }
        }        List<Long> small20IdList = new ArrayList<>(small20IdToQuantityMap.keySet());
        // 2. 计算差集：上次存在但本次不存在的SKU（需要取消低库存标识）
        List<Long> diffList = lastSmall20Set.stream()
                .filter(id -> !small20IdList.contains(id))
                .collect(Collectors.toList());
        if (!diffList.isEmpty()) {
            LambdaUpdateWrapper<PlatformProductDo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(PlatformProductDo::getInventoryLess, 0);
            updateWrapper.in(PlatformProductDo::getId, diffList);
            baseMapper.update(null, updateWrapper);
        }

        // 3. 计算新增：本次存在但上次不存在的SKU（需要标记为低库存）
        List<Long> newAddList = small20IdList.stream()
                .filter(id -> !lastSmall20Set.contains(id))
                .collect(Collectors.toList());
        if (!newAddList.isEmpty()) {
            LambdaUpdateWrapper<PlatformProductDo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(PlatformProductDo::getInventoryLess, 1);
            updateWrapper.in(PlatformProductDo::getId, newAddList);
            baseMapper.update(null, updateWrapper);
        }
        // 4. 用ZSet更新缓存（score为库存数量，便于后续按库存筛选）
        redisTemplate.delete(small20RedisKey); // 删除旧数据
        if (!small20IdToQuantityMap.isEmpty()) {
            // 批量添加到ZSet：member=SKU ID，score=库存数量
            Set<ZSetOperations.TypedTuple<Long>> tuples = new HashSet<>();
            for (Map.Entry<Long, Integer> entry : small20IdToQuantityMap.entrySet()) {
                tuples.add(new DefaultTypedTuple<>(entry.getKey(), entry.getValue().doubleValue()));
            }
            redisTemplate.opsForZSet().add(small20RedisKey, tuples);
            // 可按需设置过期时间（如果需要）
            redisTemplate.expire(small20RedisKey, 24, TimeUnit.HOURS);
        }

    }


    @Override
    public void updateProduct(PlatformUpdateReq req, Long userId, Long companyId) {
        PlatformProductDo ot = dao.selectById(req.getId());
        if (ot == null) {
            return;
        }
        PlatformStoreDo storeDo = storeService.getById(ot.getStoreId());
        if (storeDo == null) {
            return;
        }

        platformProductMappingDao.delete(new LambdaQueryWrapper<PlatformProductMappingDo>().eq(PlatformProductMappingDo::getPlatformProductId, req.getId()));
        List<String> skuList = req.getSystemSkus().stream().map(SkuAddReq::getSku).distinct().collect(Collectors.toList());

        Map<String, ProductSkuVo> skuMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(skuList)) {
            skuMap = productDao.getProductsBySku(skuList, companyId).stream().collect(Collectors.toMap(ProductSkuVo::getSku, val -> val));
        }

        Map<String, SkuAddReq> skuAddMap = req.getSystemSkus().stream().collect(Collectors.toMap(SkuAddReq::getSku, i -> i, (i1, i2) -> i1));
//        boolean isUpdate = false;
        StringBuilder systemSku = new StringBuilder();
        for (String sku : skuAddMap.keySet()) {
            SkuAddReq systemSkus = skuAddMap.get(sku);
            ProductSkuVo productSkuVo = skuMap.get(systemSkus.getSku());
            if (productSkuVo == null) {
                throw new BizException("sku:" + systemSkus.getSku() + "不存在");
            }
            if (systemSku.length() > 0) {
                systemSku.append(";");
            }
            systemSku.append(systemSkus.getSku()).append("*").append(systemSkus.getQty());
            PlatformProductMappingDo mappingDo = new PlatformProductMappingDo();
            mappingDo.setPlatformProductId(req.getId());
            mappingDo.setSystemProductId(productSkuVo.getId());
            mappingDo.setQty(systemSkus.getQty());
            platformProductMappingDao.insert(mappingDo);
        }
        PlatformProductDo entityDo = new PlatformProductDo();
        entityDo.setId(req.getId());
//        BeanUtils.copyProperties(req, entityDo);
        if (StringUtils.isBlank(ot.getParentSku())) {
            entityDo.setParentSku(req.getParentSku());
        }
        if (StaticDict.Store_PlatformCode.Amazon.getValue().equals(storeDo.getPlatformCode())) {
            if (StringUtils.isBlank(req.getShippingDayId())) {
                entityDo.setShippingDayId("-1");
            } else {
                entityDo.setShippingDayId(req.getShippingDayId());
            }
        }
        entityDo.setInventoryLink(req.getInventoryLink());
        entityDo.setProductPresale(req.getProductPresale());
        entityDo.setStockPercent(req.getStockPercent());
        entityDo.setSystemSku(systemSku.toString());
        entityDo.setMatched(StringUtils.isBlank(systemSku.toString()) ? 0 : 1);
        dao.updateById(entityDo);

        PlatformProductDo nt = dao.selectById(req.getId());
        String operateContent = this.getOperateContent(ot, nt);
        operateRecordService.operateAddRecordAndValue(operateContent, "", req.getId(), userId, null, OperateTypeEnum.PlatProduct);
    }


    /**
     * 操作日志
     *
     * @param ot
     * @param nt
     * @return
     */
    public String getOperateContent(PlatformProductDo ot, PlatformProductDo nt) {
        Map<String, Object> beforeMap = new HashMap<>();
        Map<String, Object> afterMap = new HashMap<>();
        BeanChangeUtils<CompanyDo> utils = new BeanChangeUtils<>();
        utils.contrastObj(ot, nt, beforeMap, afterMap);
        StringBuilder content = new StringBuilder();
        for (String key : beforeMap.keySet()) {
            String name = StaticDict.Operate_Log_PlatformProduct.getText(key);
            int type = StaticDict.Operate_Log_PlatformProduct.getType(key);

            if ("".equals(name)) {
                continue;
            }
            if (content.length() > 0) {
                content.append(";\r\n");
            }
            content.append(name).append("【");
            String before = type == 0 ? beforeMap.get(key).toString() : type == 1 ?  (beforeMap.get(key).equals(0) ? "是" : "否") : (beforeMap.get(key).equals(0) ? "否" : "是");
            content.append(before).append("】").append("->【");
            String after = type == 0 ? afterMap.get(key).toString() : type == 1 ? (afterMap.get(key).equals(0) ? "是" : "否") : (afterMap.get(key).equals(0) ? "否" : "是");
            content.append(after).append("】");
        }
        return content.toString();
    }



    @Override
    public AllocatePlatformUpdateRes updatePlatformProductAndReturnStock(AllocatePlatformUpdateReq bo, Long userId, Long tenantId, Long companyId) {
        Long platformProductId = bo.getPlatformProductId();
        PlatformProductDo platformProductDo = baseMapper.selectById(platformProductId);
        if (platformProductDo == null) {
            throw new BizException(SysConstant.No_Data);
        }
        platformProductMappingDao.delete(new LambdaQueryWrapper<PlatformProductMappingDo>().eq(PlatformProductMappingDo::getPlatformProductId, platformProductId));
        List<AllocatePlatformUpdateReq.ProductSysDto> productSysDtoList = bo.getProductSysDtoList();
        if (CollUtil.isEmpty(productSysDtoList)) {
            throw new BizException(SysConstant.Allocate_Match_Product_Error);
        }
        Map<String, ProductDo> skuMatch = productDao.selectList(
                Wrappers.<ProductDo>lambdaQuery()
                        .in(ProductDo::getSku, productSysDtoList.stream().map(AllocatePlatformUpdateReq.ProductSysDto::getSku).collect(Collectors.toList()))
                        .eq(ProductDo::getCompanyId, companyId)
        ).stream().collect(Collectors.toMap(ProductDo::getSku, val -> val, (i1, i2) -> i1));
        if (CollUtil.isEmpty(skuMatch) || skuMatch.size() != productSysDtoList.size()) {
            throw new BizException(SysConstant.Allocate_Match_Product_Error);
        }
        List<AllocatePlanItemDo> planItemDoList = allocatePlanItemService.lambdaQuery()
                .eq(AllocatePlanItemDo::getPlatformProductId, platformProductId)
                .eq(AllocatePlanItemDo::getDeleteFlag, SysConstant.DELETE_FLAG_FALSE)
                .isNull(AllocatePlanItemDo::getProductId)
                .list();
        //联动修改调拨产品信息
        for (AllocatePlanItemDo planItemDo : planItemDoList) {
            allocatePlanItemService.removeById(planItemDo.getId());
            List<AllocatePlanItemDo> itemList = new ArrayList<>();
            int qty = 0;
            for (AllocatePlatformUpdateReq.ProductSysDto productSysDto : productSysDtoList) {
                ProductDo productDo = skuMatch.get(productSysDto.getSku());
                AllocatePlanItemDo planItem = new AllocatePlanItemDo();
                BeanUtils.copyProperties(planItemDo, planItem);
                planItem.setId(null);
                planItem.setCreateTime(null);
                planItem.setProductId(productDo.getId());
                planItem.setProductName(productDo.getProductName());
                planItem.setSku(productDo.getSku());
                planItem.setPerBoxQty(productSysDto.getQty());
                qty += productSysDto.getQty() * planItemDo.getBoxQty();
                planItem.setPlanShipments(productSysDto.getQty() * planItemDo.getBoxQty());
                planItem.setLockQty(0);
                itemList.add(planItem);
            }
            allocatePlanItemService.saveBatch(itemList);
            AllocatePlanDo planDo = new AllocatePlanDo();
            planDo.setId(planItemDo.getOrderId());
            planDo.setTotalPlanShipments(qty);
            allocatePlanDao.updateById(planDo);
        }
        //查产品库存
        ProductStockBySkuQueryBo req = new ProductStockBySkuQueryBo();
        req.setCompanyIdList(Collections.singletonList(companyId));
        req.setSource("oms");
        req.setTenantId(tenantId);
        req.setUserId(userId);
        req.setStockAttribute(0);
        req.setWhIdList(Collections.singletonList(bo.getWhId()));
        req.setProductIds(skuMatch.values().stream().map(ProductDo::getId).collect(Collectors.toList()));
        PageResult<SkuStockPageDto> listPageBySku = productStockService.productListPageBySku(req);
        Map<Long, SkuStockPageDto> productIdMatchStock = new HashMap<>();
        if (Objects.nonNull(listPageBySku) && CollUtil.isNotEmpty(listPageBySku.getData())) {
            productIdMatchStock = listPageBySku.getData().stream().collect(Collectors.toMap(SkuStockPageDto::getProductId, val -> val, (i1, i2) -> i1));
        }
        AllocatePlatformUpdateRes res = new AllocatePlatformUpdateRes();
        res.setPlatformProductId(platformProductId);
        //构建响应
        for (AllocatePlatformUpdateReq.ProductSysDto productSysDto : productSysDtoList) {
            ProductDo productDo = skuMatch.get(productSysDto.getSku());
            // 保存映射关系
            PlatformProductMappingDo mappingDo = new PlatformProductMappingDo();
            mappingDo.setPlatformProductId(platformProductDo.getId());
            mappingDo.setSystemProductId(productDo.getId());
            mappingDo.setQty(productSysDto.getQty());
            platformProductMappingDao.insert(mappingDo);
            AllocatePlatformUpdateRes.SysProductInfo sysProductInfo = new AllocatePlatformUpdateRes.SysProductInfo();
            sysProductInfo.setProductName(productDo.getProductName());
            sysProductInfo.setProductId(productDo.getId());
            sysProductInfo.setSku(productDo.getSku());
            sysProductInfo.setQty(productSysDto.getQty());
            SkuStockPageDto skuStockPageDto = productIdMatchStock.get(productDo.getId());
            if (Objects.nonNull(skuStockPageDto)) {
                sysProductInfo.setDeliveryWhAvailableStock(skuStockPageDto.getAvailableAmount());
                sysProductInfo.setDeliveryWhInTransitStock(skuStockPageDto.getTransportAmount());
            }
            res.getSysProductInfoList().add(sysProductInfo);
        }
        return res;
    }

    @Override
    public PlatformProductDto updateInit(Long id, Long companyId) {
        PlatformProductDo productDo = dao.selectOne(new LambdaQueryWrapper<PlatformProductDo>()
                .eq(PlatformProductDo::getId, id)
                .eq(PlatformProductDo::getCompanyId, companyId));
        if (productDo == null) {
            return null;
        }
        PlatformProductDto record = new PlatformProductDto();
        BeanUtils.copyProperties(productDo, record);
        List<PlatformProductMappingDto> mappingMap = platformProductMappingDao.getList(Collections.singletonList(id), companyId);
        record.setMappings(mappingMap);
        return record;
    }

    @Override
    public String add(PlatformAddReq req, Long userId, Long companyId) {
        String s = this.addNoEx(req, userId, companyId, null);
        if (StringUtils.isNotBlank(s)) {
            throw new BizException(s);
        }
        return null;
    }

    @Override
    public String addNoEx(PlatformAddReq req, Long userId, Long companyId, Long tenantId) {
        if (req.getStockPercent() != null && (req.getStockPercent() < 0 || req.getStockPercent() > 1)) {
            return "库存预留占比需在 0-1 之间";
        }
        req.setPlatformSku(req.getPlatformSku().trim());
        Map<Long, String> storeMap = storeService.getList(companyId).stream().collect(Collectors.toMap(PlatformStoreRes::getId, i -> i.getStoreName() + "(" + i.getStoreCode() + ")"));
        List<Long> storeIds = new ArrayList<>();
        if (req.getStoreId() == null || req.getStoreId() == -1L) {
            storeIds.addAll(storeMap.keySet());
        } else {
            storeIds.add(req.getStoreId());
        }
        if (storeIds.isEmpty()) {
            return req.getPlatformSku() + "无店铺";
        }
        //验证平台sku唯一性
        List<Object> count = dao.selectObjs(new LambdaQueryWrapper<PlatformProductDo>()
                .select(PlatformProductDo::getStoreId)
                .eq(PlatformProductDo::getPlatformSku, req.getPlatformSku())
                .in(PlatformProductDo::getStoreId, storeIds));
        if (!count.isEmpty()) {
            return StringsUtil.createI18Message(SysConstant.PlatformProduct_Mapping_Exist, req.getPlatformSku(), storeMap.get(Long.parseLong(count.get(0).toString())));
        }
        List<String> skuList = req.getSystemSkus().stream().map(SkuAddReq::getSku).distinct().collect(Collectors.toList());
        if (skuList.isEmpty()) {
            return req.getPlatformSku() + " 无系统sku";
        }
        Map<String, Long> skuMap = productDao.getProductsBySku(skuList, companyId).stream().collect(Collectors.toMap(ProductSkuVo::getSku, ProductSkuVo::getId));
        for (SkuAddReq systemSkus : req.getSystemSkus()) {
            if (skuMap.get(systemSkus.getSku()) == null) {
                return "不存在系统sku：" + systemSkus.getSku();
            }
        }

        for (Long storeId : storeIds) {
            PlatformProductDo entityDo = new PlatformProductDo();
            entityDo.setCompanyId(companyId);
            if (tenantId != null) {
                entityDo.setTenantId(tenantId);
            }
            entityDo.setInventoryLink(req.getInventoryLink());
            entityDo.setProductPresale(req.getProductPresale());
            entityDo.setParentSku(req.getParentSku());
            entityDo.setStoreId(storeId);
            entityDo.setShippingDayId(req.getShippingDayId());
            entityDo.setPlatformSku(req.getPlatformSku());
            entityDo.setStockPercent(req.getStockPercent());
            entityDo.setMatched(req.getSystemSkus().isEmpty() ? 0 : 1);

            Map<String, SkuAddReq> skuAddMap = req.getSystemSkus().stream().collect(Collectors.toMap(SkuAddReq::getSku, i -> i, (i1, i2) -> i1));
            StringBuilder systemSku = new StringBuilder();
            for (String sku : skuAddMap.keySet()) {
                if (systemSku.length() > 0) {
                    systemSku.append(",");
                }
                systemSku.append(sku).append("*").append(skuAddMap.get(sku).getQty());
            }
            entityDo.setSystemSku(systemSku.toString());
            dao.insert(entityDo);
            for (String sku : skuAddMap.keySet()) {
                SkuAddReq systemSkus = skuAddMap.get(sku);
                PlatformProductMappingDo mappingDo = new PlatformProductMappingDo();
                mappingDo.setPlatformProductId(entityDo.getId());
                mappingDo.setSystemProductId(skuMap.get(systemSkus.getSku()));
                mappingDo.setQty(systemSkus.getQty());
                platformProductMappingDao.insert(mappingDo);
            }
            operateRecordService.operateAddRecordAndValue("创建平台SKU", "", entityDo.getId(), userId, null, OperateTypeEnum.PlatProduct);
        }
        return null;
    }


    @Override
    public int delete(List<Long> ids, Long userId) {
        return dao.updateDelete(ids, userId);
    }

    @Override
    public SingleResult pageInit(Long companyId) {
        Map<String, Object> result = new HashMap<>();
        result.put("storeList", storeService.getList(companyId));
        result.put("platformCode", StaticDict.getStore_PlatformCode());
        return SingleResult.success(result);
    }

    @Override
    public List<PlatformProductDto> getList(Map<String, Object> map) {
        List<PlatformProductDto> list = dao.getList(map);
        return list;
    }

    @Override
    public PageResult getListPage(Map<String, Object> map) {
//        IPage<PlatformProductDto> page = pageInit(map);
//        page = dao.getList(page, map);
        map.put("customer", customer);
        int currentPage = map.get("current") != null ? Integer.parseInt(map.get("current").toString()) : 10;
        int pageSize = map.get("pageSize") != null ? Integer.parseInt(map.get("pageSize").toString()) : 10;
        PageHelper.startPage(currentPage, pageSize);
        List<PlatformProductDto> page = dao.getList(map);
        PageInfo<PlatformProductDto> pageInfo = new PageInfo<>(page);
        //获取系统sku
        if (!page.isEmpty()) {
            Map<Long, List<PlatformProductMappingDto>> mappingMap = platformProductMappingDao.getList(page
                            .stream().map(PlatformProductDto::getId).collect(Collectors.toList()), map.get("companyId"))
                    .stream().collect(Collectors.groupingBy(PlatformProductMappingDto::getPlatformProductId));
            for (PlatformProductDto record : page) {
                record.setMappings(mappingMap.get(record.getId()));
                if (record.getMappings() == null) {
                    continue;
                }
                //是否开启预售
                boolean presale = (record.getStorePresale() == null || record.getStorePresale() == 0) && (record.getProductPresale() == null || record.getProductPresale() == 0);
                //计算出 回传到平台的数量 todo
                Integer canUseAmount = null;
                for (PlatformProductMappingDto mapping : record.getMappings()) {
                    int amount = mapping.getSystemQuantity() + (presale ? mapping.getInTransitQty():  0) - mapping.getToDealQty();
                    if (canUseAmount == null || canUseAmount > amount) {
                        canUseAmount = amount;
                    }
                }
                record.setSystemCanUseAmount(canUseAmount);
            }
        }
        PageResult result = new PageResult(page, currentPage, pageSize, (int)pageInfo.getTotal(), pageInfo.getPages());
        return result;
    }

    private IPage<PlatformProductDto> pageInit(Map<String, Object> map) {
        IPage<PlatformProductDto> page = new Page<>();
        page.setSize(map.get("pageSize") != null ? Long.parseLong(map.get("pageSize").toString()) : 10);
        page.setCurrent(map.get("current") != null ? Long.parseLong(map.get("current").toString()) : 1);
        return page;
    }


    @Override
    public void getPlatformProductTemplate(HttpServletResponse response, Long companyId) throws IOException {
        TemplateExportParams params = new TemplateExportParams(
                "excelTemplates/ProductRelation_Import.xlsx", true);

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment;filename=ProductRelation_Import.xlsx");
        //导出数据
        try (Workbook book = ExcelExportUtil.exportExcel(params, this.buildPlatformProducTemplateSheetData(companyId))) {
            book.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            response.getOutputStream().flush();
            response.getOutputStream().close();
        }
    }

    private Map<String, Object> buildPlatformProducTemplateSheetData(Long companyId) {
        //每个sheet的数据对应一个map
        Map<String, Object> sheetMap = new HashMap<>(1);
        //处理第一个sheet(店铺)
        sheetMap.put("storeList", storeService.getList(companyId));
        return sheetMap;
    }

    @Override
    public PlatformProductImportRes importT(MultipartFile file, Long userId, Long companyId, Long tenantId) {
        List<PlatformProductImportVo> zoneTempImportVos = null;
        try {
            zoneTempImportVos = ExcelUtils.importExcel(file, 1, 0, PlatformProductImportVo.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        List<PlatformStoreRes> storeList = storeService.getList(companyId);
        Map<String, Long> storeMap = storeList.stream().collect(Collectors.toMap(PlatformStoreRes::getStoreCode, PlatformStoreRes::getId));

        List<PlatformProductImportVo> successTempRuleList = new ArrayList<>();
        List<PlatformProductErrorExportVo> errorExportVos = new ArrayList<>();
        List<ErrorInfo> errorList = new ArrayList<>();
        Map<String, List<PlatformProductImportVo>> importMap = zoneTempImportVos.stream().collect(Collectors.groupingBy(i -> i.getPlatformSku() + "&&&&&&" + i.getStoreCode()));
        Set<String> skus = new HashSet<>();
        List<PlatformAddReq> addReqList = new ArrayList<>();
        for (String key : importMap.keySet()) {
            String storeCode = key.split("&&&&&&")[1];
            String platformSku = key.split("&&&&&&")[0];
            Long storeId = storeMap.get(storeCode);
            if (storeId == null && !"全部".equals(storeCode)) {
                storeId = -2L;
            }
            List<PlatformProductImportVo> importVos = importMap.get(key);
            PlatformAddReq addReq = new PlatformAddReq(storeId, storeCode, importVos.get(0).getParentSku(), platformSku, importVos.get(0).getStockPercent());
            List<SkuAddReq> systemSkus = new ArrayList<>();
            for (PlatformProductImportVo importVo : importVos) {
                systemSkus.add(new SkuAddReq(importVo.getSku(), importVo.getQty()));
                skus.add(importVo.getSku());//所有的本地sku
            }
            addReq.setSystemSkus(systemSkus);
//            String msg = this.addNoEx(addReq, userId, companyId, null);
//            if (StringUtils.isNotBlank(msg)) {
//                builder.append(msg);
//            }
            addReqList.add(addReq);
        }
        //验证
        List<String> platformSkuList = addReqList.stream().map(PlatformAddReq::getPlatformSku).collect(Collectors.toList());
        Map<String, Integer> platformSkuMap = new HashMap<>();
        Map<String, Long> platformProdcutIdMap = new HashMap<>();

        for (List<String> skuList : ListUtil.partition(platformSkuList, 5000)) {
            List<PlatformProductDo> platformProductDoList = dao.selectList(new LambdaQueryWrapper<PlatformProductDo>().in(PlatformProductDo::getPlatformSku, skuList).eq(PlatformProductDo::getCompanyId, companyId));
            Map<String, Integer> thisMap = platformProductDoList.stream().collect(Collectors.toMap(i -> i.getPlatformSku() + "&&&&&" + i.getStoreId(), PlatformProductDo::getMatched, (v1, v2) -> v1));
            platformSkuMap.putAll(thisMap);
            Map<String, Long> thisProductMap = platformProductDoList.stream().collect(Collectors.toMap(i -> i.getPlatformSku() + "&&&&&" + i.getStoreId(), PlatformProductDo::getId, (v1, v2) -> v1));
            platformProdcutIdMap.putAll(thisProductMap);

        }
        List<String> skuArray = new ArrayList<>(skus);
        Map<String, Long> skuMap = new HashMap<>();
        if (!skuArray.isEmpty()) {
            List<List<String>> partition = ListUtil.partition(skuArray, 5000);
            for (List<String> list : partition) {
                Map<String, Long> thisMap = productDao.getProductsBySku(list, companyId).stream().collect(Collectors.toMap(ProductSkuVo::getSku, ProductSkuVo::getId));
                skuMap.putAll(thisMap);
            }
        }

        Map<Long, String> storeMapId = storeList.stream().collect(Collectors.toMap(PlatformStoreRes::getId, PlatformStoreRes::getStoreCode));

        List<PlatformProductDo> batchInsertReqs = new ArrayList<>();
        List<PlatformProductDo> batchUpdateReqs = new ArrayList<>();
        List<PlatformProductBatchInsertReq> productBatchInsertReqList = new ArrayList<>();
        for (PlatformAddReq req : addReqList) {
            StringBuilder builder = new StringBuilder();
            if (req.getStoreId() != null && req.getStoreId() == -2L) {
                builder.append("店铺不存在;");
            } else if (storeMap.isEmpty()) {
                builder.append("无店铺;");
            }
            if (req.getStockPercent() != null && (req.getStockPercent() < 0 || req.getStockPercent() > 1)) {
                builder.append("库存预留占比需在 0-1 之间;");
            }
            List<Long> storeIds = new ArrayList<>();
            if (req.getStoreId() == null) {
                Collection<Long> values = storeMap.values();
                storeIds.addAll(values);
            } else {
                storeIds.add(req.getStoreId());
            }
            //此代码开启后将会更新 已存在的映射关系  开启时 记得关闭删除映射表
//            for (Long storeId : storeIds) {
//                Integer matched = platformSkuMap.get(req.getPlatformSku() + "&&&&&" + storeId);
//                if (matched != null && matched == 1) {
//                    builder.append(StringsUtil.createI18Message(SysConstant.PlatformProduct_Mapping_Exist, req.getPlatformSku(), storeMapId.get(storeId)));
//                    break;
//                }
//            }
            for (SkuAddReq systemSkus : req.getSystemSkus()) {
                if (skuMap.get(systemSkus.getSku()) == null) {
                    builder.append("系统sku不存在;");
                    break;
                }
            }
            if (StringUtils.isNotBlank(builder.toString())) {
                for (SkuAddReq systemSkus : req.getSystemSkus()) {
                    errorExportVos.add(new PlatformProductErrorExportVo(builder.toString(), req.getStoreCode(), req.getParentSku(), req.getPlatformSku(), req.getStockPercent(), systemSkus.getSku(), systemSkus.getQty()));

                }
            } else {
                successTempRuleList.add(new PlatformProductImportVo(req.getStoreCode(), req.getParentSku(), req.getPlatformSku(), req.getStockPercent(), null, null));
                Map<String, SkuAddReq> skuAddMap = req.getSystemSkus().stream().collect(Collectors.toMap(SkuAddReq::getSku, i -> i, (i1, i2) -> i1));
                StringBuilder systemSku = new StringBuilder();
                for (String sku : skuAddMap.keySet()) {
                    if (systemSku.length() > 0) {
                        systemSku.append(",");
                    }
                    systemSku.append(sku).append("*").append(skuAddMap.get(sku).getQty());
                }
                for (Long storeId : storeIds) {
                    Long id = platformProdcutIdMap.get(req.getPlatformSku() + "&&&&&" + storeId);
                    if (id != null) {
                        PlatformProductDo platformProductDo = new PlatformProductDo(storeId, req.getParentSku(), req.getPlatformSku(), req.getStockPercent(), req.getInventoryLink(), null, systemSku.toString(),
                                req.getSystemSkus().isEmpty() ? 0 : 1, companyId, tenantId, userId);
                        platformProductDo.setId(id);
                        batchUpdateReqs.add(platformProductDo);
                    } else {
                        batchInsertReqs.add(new PlatformProductDo(storeId, req.getParentSku(), req.getPlatformSku(), req.getStockPercent(), req.getInventoryLink(), 0, systemSku.toString(),
                                req.getSystemSkus().isEmpty() ? 0 : 1, companyId, tenantId, userId));
                    }
                    for (SkuAddReq systemSkus : req.getSystemSkus()) {
                        Long systemProductId = skuMap.get(systemSkus.getSku());
                        productBatchInsertReqList.add(new PlatformProductBatchInsertReq(id, systemProductId, systemSkus.getSku(), systemSkus.getQty(), req.getPlatformSku(), storeId));
                    }
                }

            }
        }
        if (!batchInsertReqs.isEmpty()) {
            List<List<PlatformProductDo>> partition = ListUtil.partition(batchInsertReqs, 5000);
            for (List<PlatformProductDo> platformProductDoList : partition) {
                dao.batchInsert(platformProductDoList);
            }
            batchInsertReqs.forEach(insert -> productBatchInsertReqList.stream().filter(item -> item.getPlatformProductId() == null && item.getPlatformSku().equals(insert.getPlatformSku()) && item.getStoreId().equals(insert.getStoreId()))
                    .forEach(item -> item.setPlatformProductId(insert.getId())));
        }
        for (PlatformProductDo batchUpdateReq : batchUpdateReqs) {
            dao.updateById(batchUpdateReq);
        }
        List<Long> updateIds = batchUpdateReqs.stream().map(PlatformProductDo::getId).collect(Collectors.toList());
        if (!updateIds.isEmpty()) {
            platformProductMappingDao.delete(new LambdaQueryWrapper<PlatformProductMappingDo>().in(PlatformProductMappingDo::getPlatformProductId, updateIds));
        }
        List<PlatformProductBatchInsertReq> collect = productBatchInsertReqList.stream().filter(item -> item.getPlatformProductId() != null).collect(Collectors.toList());
        if (!collect.isEmpty()) {
            List<List<PlatformProductBatchInsertReq>> partition1 = ListUtil.partition(collect, 5000);
            for (List<PlatformProductBatchInsertReq> platformProductBatchInsertReqs : partition1) {
                platformProductMappingDao.batchInsert(platformProductBatchInsertReqs);
            }
        }
        PlatformProductImportRes res = new PlatformProductImportRes();
        res.setFailNum(errorExportVos.size());
        res.setSuccessNum(successTempRuleList.size());
        if (errorExportVos.isEmpty()) {
            return res;
        }
        String fileName = "错误_产品映射" + TimeUtils.getCurrentDateFormat("MMddHHmmss") + ".xlsx";

        try {
            ExcelUtils.exportExcelToSave(errorExportVos, PlatformProductErrorExportVo.class, fileName, new ExportParams(), filePathTemp);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String objectNameTemporary = "";
        if (filePath.startsWith("http")) {
            try {
                objectNameTemporary = AliOss.temporaryFile2(fileName, new File(filePathTemp + File.separator + fileName));
            } catch (Exception e) {
                e.printStackTrace();
                log.error("导出文件失败" + e.getMessage());
            }
            res.setFailFileUrl(fileUrl + objectNameTemporary);
        } else {
            res.setFailFileUrl(fileUrl + fileName);
        }
        res.setFileName(fileName);
        res.setErrorList(errorList);
        return res;
    }


    @Override
    public void platformProductExport(Map<String, Object> map, HttpServletResponse response) {
        List<PlatformProductExportVo> exportVos = dao.getExportList(map);
        if (exportVos.size() > 70000) {
            throw new BizException(SysConstant.File_Export_ToMuch, 70000);
        }
        String fileName = "产品映射" + TimeUtils.getCurrentDateFormat("MMddHHmmss");
        ExportParams excelParam = new ExportParams();
        try {
            ExcelUtils.exportExcel(exportVos, PlatformProductExportVo.class, fileName, excelParam, response, "xls");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 根据平台sku 获取映射关系
     */
    //获取店铺下所有的产品映射
    @Override
    public List<ProductSysDto> getSystemSkuList(List<String> platformSkus, Long storeId) {
        return dao.getSysProduct(platformSkus, storeId);
    }


    @Override
    public void insert(PlatformProductDo productDo, Long userId) {
        if (productDo.getProductPresale() == null) {
            productDo.setProductPresale(0);
        }
        dao.insert(productDo);
    }

    @Override
    public void save(List<PlatformProductDo> productDoList, String platformCode, boolean delete, Long storeId, Long companyId) {
        if (productDoList.isEmpty()) {
            return;
        }
        if (StaticDict.Store_PlatformCode.Rakuten.getValue().equals(platformCode) || StaticDict.Store_PlatformCode.Yahoo.getValue().equals(platformCode)) {
            //根据父sku 去删除不存在
            List<String> allPlatformSkus = productDoList.stream().map(PlatformProductDo::getPlatformSku).distinct().collect(Collectors.toList());
            if (!allPlatformSkus.isEmpty() && delete) {
                LambdaQueryWrapper<PlatformProductDo> selectWrapper = new LambdaQueryWrapper<>();
                selectWrapper.select(PlatformProductDo::getId);
                selectWrapper.eq(PlatformProductDo::getParentSku, productDoList.get(0).getParentSku());
                selectWrapper.eq(PlatformProductDo::getCompanyId, companyId);
                selectWrapper.eq(PlatformProductDo::getStoreId, storeId);
                selectWrapper.notIn(PlatformProductDo::getPlatformSku, allPlatformSkus);
                List<Long> ids = dao.selectList(selectWrapper).stream().map(PlatformProductDo::getId).collect(Collectors.toList());
                if (!ids.isEmpty()) {
                    LambdaUpdateWrapper<PlatformProductDo> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.in(PlatformProductDo::getId, ids);
                    updateWrapper.set(PlatformProductDo::getDeleteFlag, 1);
                    updateWrapper.set(PlatformProductDo::getDeleteBy, -1);
                    updateWrapper.set(PlatformProductDo::getDeleteTime, new Date());
                    dao.update(null, updateWrapper);
                }

            }
        }

        Map<String, PlatformProductDo> collect = productDoList.stream().collect(Collectors.toMap(PlatformProductDo::getPlatformSku, i -> i, (i1, i2) -> i1));
        List<PlatformProductDo> updateList = new ArrayList<>(collect.values());
        List<List<PlatformProductDo>> partionProductList = ListUtil.partition(updateList, 5000);
        for (List<PlatformProductDo> platformProductDoList : partionProductList) {
            Map<String, Long> productMap = dao.selectList(new LambdaQueryWrapper<PlatformProductDo>().select(PlatformProductDo::getPlatformSku, PlatformProductDo::getId).eq(PlatformProductDo::getCompanyId, companyId)
                            .eq(PlatformProductDo::getStoreId, storeId)
                            .in(PlatformProductDo::getPlatformSku, platformProductDoList.stream().map(PlatformProductDo::getPlatformSku).collect(Collectors.toList())))
                    .stream().collect(Collectors.toMap(PlatformProductDo::getPlatformSku, PlatformProductDo::getId, (i1, i2) -> i1));
            Map<Long, List<PlatformProductMappingDto>> mappingMap;
            if (!productMap.isEmpty()) {
                mappingMap = platformProductMappingDao.getList(new ArrayList<>(productMap.values()), companyId)
                        .stream().collect(Collectors.groupingBy(PlatformProductMappingDto::getPlatformProductId));
            } else {
                mappingMap = new HashMap<>();
            }
            List<String> platformSkus = new ArrayList<>();
            for (PlatformProductDo productDo : platformProductDoList) {
                //如果映射表没有 就添加
                if (mappingMap.containsKey(productMap.get(productDo.getPlatformSku()))) {
                    continue;
                }
                platformSkus.add(productDo.getPlatformSku());
            }
            Map<String, Long> skuMap = new HashMap<>();
            if (!platformSkus.isEmpty()) {
                //匹配本地产品表
                skuMap = productDao.getProductsBySku(platformSkus, companyId).stream().collect(Collectors.toMap(ProductSkuVo::getSku, ProductSkuVo::getId, (i1, i2) -> i1));
            }

            for (PlatformProductDo platformProductDo : platformProductDoList) {
                Long platformProductId = productMap.get(platformProductDo.getPlatformSku());
                boolean match = mappingMap.containsKey(platformProductId) || !skuMap.containsKey(platformProductDo.getPlatformSku());
                if (!match) {
                    platformProductDo.setMatched(1);
                    platformProductDo.setSystemSku(platformProductDo.getPlatformSku() + "*1");
                }
                Long id = productMap.get(platformProductDo.getPlatformSku());
                if (id == null) {
                    //亚马逊平台 且 不是FBM 则新增的时候过滤掉
                    if (StaticDict.Store_PlatformCode.Amazon.getValue().equals(platformCode) && !"DEFAULT".equals(platformProductDo.getFulfillmentChannelCode())) {
                        continue;
                    }
                    this.insert(platformProductDo, null);
                } else {
                    platformProductDo.setId(id);
                    this.updateById(platformProductDo);
                }
                if (skuMap.isEmpty()) {
                    continue;
                }
                if (match) {
                    continue;
                }
                PlatformProductMappingDo mappingDo = new PlatformProductMappingDo();
                mappingDo.setPlatformProductId(platformProductDo.getId());
                mappingDo.setSystemProductId(skuMap.get(platformProductDo.getPlatformSku()));
                mappingDo.setQty(1);
                platformProductMappingDao.insert(mappingDo);
            }
        }

    }


    /**
     * 单个商品同步
     */
    @Override
    public void manualSyncPlatformProduct(ManualSyncPlatformProductReq req, Long userId) {
        PlatformStoreDo storeDo = storeService.getById(req.getStoreId());
        if (storeDo == null) {
            return;
        }
        if (storeDo.getAuthSyncStatus() != 1) {
            throw new BizException("该店铺" + storeDo.getStoreCode() + "授权过期或暂停同步");
        }
        if (req.getMode() == 0) {
            //单个商品同步
            if (StaticDict.Store_PlatformCode.Amazon.getValue().equals(storeDo.getPlatformCode())) {
                //亚马逊
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Amazon, JSON.toJSONString(new AmazonItemConsumerReq(storeDo, req.getPlatformSku())));
            } else if (StaticDict.Store_PlatformCode.Rakuten.getValue().equals(storeDo.getPlatformCode())) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Rakuten, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, req.getParentSku(), req.getPlatformSku())));
            } else if (StaticDict.Store_PlatformCode.Yahoo.getValue().equals(storeDo.getPlatformCode())) {
                if (StringUtils.isBlank(req.getParentSku())) {
                    throw new BizException("Yahoo 同步商品 需要商品代码(itemCode)");
                }
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Yahoo, JSON.toJSONString(new YahooGetItemReq(req.getParentSku(), storeDo)));
            }
            else if (StaticDict.Store_PlatformCode.Qoo10.getValue().equals(storeDo.getPlatformCode())) {
                if (StringUtils.isBlank(req.getParentSku())) {
                    throw new BizException("Qoo10 同步商品 需要商品代码(sellerCode)");
                }
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Qoo10_ParentSku, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, req.getParentSku(), null)));
            }
            else if (StaticDict.Store_PlatformCode.Wowma.getValue().equals(storeDo.getPlatformCode())) {
                if (StringUtils.isBlank(req.getParentSku())) {
                    throw new BizException("wowma 同步商品 需要管理番号(itemCode)");
                }
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Wowma, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, req.getParentSku(), null)));

            }
            else {
                throw new BizException("该平台：" + storeDo.getPlatformCode() + "暂未对接");
            }
        } else {
            if (StaticDict.Store_PlatformCode.Amazon.getValue().equals(storeDo.getPlatformCode())) {
                //亚马逊
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Amazon, JSON.toJSONString(new AmazonItemConsumerReq(storeDo, null)));
            } else if (StaticDict.Store_PlatformCode.Rakuten.getValue().equals(storeDo.getPlatformCode())) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Rakuten, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, null, null)));
            } else if (StaticDict.Store_PlatformCode.Yahoo.getValue().equals(storeDo.getPlatformCode())) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_ItemList_Yahoo, JSON.toJSONString(storeDo));
            } else if (StaticDict.Store_PlatformCode.Qoo10.getValue().equals(storeDo.getPlatformCode())) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Qoo10, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, null, null)));
            } else if (StaticDict.Store_PlatformCode.Wowma.getValue().equals(storeDo.getPlatformCode())) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Wowma, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, null, null)));
            }
            else if (StaticDict.Store_PlatformCode.SuperDelivery.getValue().equals(storeDo.getPlatformCode())) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_SuperDelivery, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, null, null)));
            }
        }
    }


    //获取下载导入模板
    @Override
    public void getPlatformProductUpdateTemplate(HttpServletResponse response, Long companyId) throws IOException {
        TemplateExportParams params = new TemplateExportParams(
                "excelTemplates/PlatformProductUpdate_Import.xlsx", true);

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment;filename=PlatformProductUpdate_Import.xlsx");
        //导出数据
        try (Workbook book = ExcelExportUtil.exportExcel(params, this.buildTemplateSheetData(companyId))) {
            book.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            response.getOutputStream().flush();
            response.getOutputStream().close();
        }
    }

    private Map<String, Object> buildTemplateSheetData(Long companyId) {
        //每个sheet的数据对应一个map
        Map<String, Object> sheetMap = new HashMap<>(1);
        //处理第一个sheet(店铺)
        sheetMap.put("storeList", storeService.getList(companyId));
        return sheetMap;
    }




    //导入更新库存联动 等等
    @Override
    public void importBatchUpdate(MultipartFile file, Long userId, Long companyId) {
        List<UpdatePlatProductImportVo> importTrackNoVos = null;
        try {
            importTrackNoVos = ExcelUtils.importExcel(file, 1, 0,  UpdatePlatProductImportVo.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (importTrackNoVos.isEmpty()) {
            return;
        }

        //rabbitmq 异步去更新 量太大的话
        Map<String, Long> storeMap = storeService.list(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getCompanyId, companyId))
                .stream().collect(Collectors.toMap(PlatformStoreDo::getStoreCode, PlatformStoreDo::getId, (k1, k2) -> k1));
        List<UpdatePlatProductImportVo> voList = importTrackNoVos.stream().filter(i -> StringUtils.isNotBlank(i.getPlatformSku()) && StringUtils.isNotBlank(i.getStoreCode()) &&
                storeMap.get(i.getStoreCode()) != null && (i.getInventoryLink() != null || i.getStockPercent() != null || i.getProductPresale() != null || StringUtils.isNotBlank(i.getShippingDayId()))).collect(Collectors.toList());

        Map<String, List<UpdatePlatProductImportVo>> collect = voList.stream()
                .collect(Collectors.groupingBy(i -> storeMap.get(i.getStoreCode()) + "_____" + i.getStockPercent() + "_____" + i.getInventoryLink() + "_____" + i.getProductPresale()));
        for (Map.Entry<String, List<UpdatePlatProductImportVo>> stringListEntry : collect.entrySet()) {
            List<UpdatePlatProductImportVo> updatePlatProductImportVos = stringListEntry.getValue();
            Long storeId = Long.parseLong(stringListEntry.getKey().split("_____")[0]);

            List<List<UpdatePlatProductImportVo>> partition = ListUtil.partition(updatePlatProductImportVos, 5000);
            for (List<UpdatePlatProductImportVo> platProductImportVos : partition) {
                PlatProductUpdateConsumerReq consumerReq = new PlatProductUpdateConsumerReq(updatePlatProductImportVos.get(0).getStockPercent(),
                        updatePlatProductImportVos.get(0).getInventoryLink(), updatePlatProductImportVos.get(0).getProductPresale(), updatePlatProductImportVos.get(0).getShippingDayId(), storeId, userId, companyId,
                        platProductImportVos.stream().map(UpdatePlatProductImportVo::getPlatformSku).collect(Collectors.toList()));
                rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformProduct_ImportUpdate, JSON.toJSONString(consumerReq));
            }

        }

    }

    @Override
    public void importUpdate(PlatProductUpdateConsumerReq req) {
        if (CollUtil.isEmpty(req.getPlatformSkus())) {
            return;
        }
        //获取id
        List<PlatformProductDo> list = dao.selectList(new LambdaQueryWrapper<PlatformProductDo>()
                        .select(PlatformProductDo::getId, PlatformProductDo::getPlatformSku)
                .eq(PlatformProductDo::getStoreId, req.getStoreId()).in(PlatformProductDo::getPlatformSku, req.getPlatformSkus()));
        if (CollUtil.isEmpty( list)) {
            return;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("updateInventoryLink", req.getInventoryLink());
        map.put("updateStockPercent", req.getStockPercent());
        map.put("updateProductPresale", req.getProductPresale());
        map.put("updateShippingDayId", req.getShippingDayId());
        map.put("companyId", req.getCompanyId());
        map.put("userId", req.getUserId());
        map.put("ids", list.stream().map(PlatformProductDo::getId).collect(Collectors.toList()));
        this.updateInventoryBatch(map);
    }


    //获取下载删除模板
    @Override
    public void getPlatformProductDeleteParentSkuTemplate(HttpServletResponse response, Long companyId) throws IOException {
        TemplateExportParams params = new TemplateExportParams(
                "excelTemplates/PlatformProductDeleteParentSku.xlsx", true);

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment;filename=PlatformProductDeleteParentSku.xlsx");
        //导出数据
        try (Workbook book = ExcelExportUtil.exportExcel(params, this.buildTemplateSheetData(companyId))) {
            book.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            response.getOutputStream().flush();
            response.getOutputStream().close();
        }
    }


    @Override
    public void getPlatformProductDeletePlatformSkuTemplate(HttpServletResponse response, Long companyId) throws IOException {
        TemplateExportParams params = new TemplateExportParams(
                "excelTemplates/PlatformProductDeletePlatformSku.xlsx", true);

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment;filename=PlatformProductDeletePlatformSku.xlsx");
        //导出数据
        try (Workbook book = ExcelExportUtil.exportExcel(params, this.buildTemplateSheetData(companyId))) {
            book.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            response.getOutputStream().flush();
            response.getOutputStream().close();
        }
    }




    @Override
    public void importDelete(MultipartFile file, Integer deleteType, Long userId, Long companyId) {
        if (deleteType == null) {
            return;
        }
        List<DeleteSkuImportVo> importTrackNoVos = null;
        try {
            importTrackNoVos = ExcelUtils.importExcel(file, 1, 0,  DeleteSkuImportVo.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (importTrackNoVos.isEmpty()) {
            return;
        }
        Map<String, Long> storeMap = storeService.getList(companyId).stream().collect(Collectors.toMap(PlatformStoreRes::getStoreCode, PlatformStoreRes::getId));
        Map<String, List<DeleteSkuImportVo>> deleteMap = importTrackNoVos.stream().filter(i -> StringUtils.isNotBlank(i.getSku()) && StringUtils.isNotBlank(i.getStoreCode())).collect(Collectors.groupingBy(DeleteSkuImportVo::getStoreCode));
        for (String storeCode : deleteMap.keySet()) {
            Long storeId = storeMap.get(storeCode);
            if (storeId == null) {
                continue;
            }
            List<String> skus = deleteMap.get(storeCode).stream().map(DeleteSkuImportVo::getSku).collect(Collectors.toList());
            if (CollUtil.isEmpty(skus)) {
                continue;
            }
            LambdaQueryWrapper<PlatformProductDo> selectWrapper = new LambdaQueryWrapper<>();
            selectWrapper.select(PlatformProductDo::getId);
            selectWrapper.eq(PlatformProductDo::getCompanyId, companyId);
            selectWrapper.eq(PlatformProductDo::getStoreId, storeId);
            if (deleteType == 0) {
                selectWrapper.in(PlatformProductDo::getPlatformSku, skus);
            }
            else if (deleteType == 1) {
                //按父sku删除
                selectWrapper.in(PlatformProductDo::getParentSku, skus);
            }
            else {
                return;
            }
            List<Long> ids = dao.selectList(selectWrapper).stream().map(PlatformProductDo::getId).collect(Collectors.toList());
            if (!ids.isEmpty()) {
                LambdaUpdateWrapper<PlatformProductDo> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.in(PlatformProductDo::getId, ids);
                updateWrapper.set(PlatformProductDo::getDeleteFlag, 1);
                updateWrapper.set(PlatformProductDo::getDeleteBy, userId);
                updateWrapper.set(PlatformProductDo::getDeleteTime, new Date());
                dao.update(null, updateWrapper);
            }
        }
    }

    /**
     * 批量更新库存预留占比 和 库存是否联动
     *
     * @param map
     */
    @Override
    public void updateInventoryBatch(Map<String, Object> map) {
        Object updateInventoryLink = map.get("updateInventoryLink");
        Object updateStockPercent = map.get("updateStockPercent");
        Object updateProductPresale = map.get("updateProductPresale");
        Object updateShippingDayId = map.get("updateShippingDayId");

        if (updateStockPercent == null && updateInventoryLink == null && updateProductPresale == null && updateShippingDayId == null) {
            return;
        }
        List<PlatformProductDto> list = dao.getList(map);
        if (list.isEmpty()) {
            return;
        }
        Long userId = map.get("userId") != null ? Long.parseLong(map.get("userId").toString()) : null;
        List<List<PlatformProductDto>> partition = ListUtil.partition(list, 5000);
        List<OperateRecordDo> operateRecordDos = new ArrayList<>();
        for (List<PlatformProductDto> platformProductDtos : partition) {
            StringBuilder content = new StringBuilder("批量修改,");
            LambdaUpdateWrapper<PlatformProductDo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.in(PlatformProductDo::getId, platformProductDtos.stream().map(PlatformProductDto::getId).collect(Collectors.toList()));
            if (updateStockPercent != null) {
                updateWrapper.set(PlatformProductDo::getStockPercent, updateStockPercent);
                content.append("库存预留占比：").append(updateStockPercent).append(";");
            }
            if (updateInventoryLink != null) {
                updateWrapper.set(PlatformProductDo::getInventoryLink, updateInventoryLink);
                content.append("库存是否联动：").append(Objects.equals(updateInventoryLink.toString(), "1") ? "是" : "否").append(";");
            }
            if (updateProductPresale != null) {
                updateWrapper.set(PlatformProductDo::getProductPresale, updateProductPresale);
                content.append("商品预售：").append(Objects.equals(updateProductPresale.toString(), "0") ? "开启" : "关闭").append(";");
            }
            if (updateShippingDayId != null) {
                updateWrapper.set(PlatformProductDo::getShippingDayId, updateShippingDayId);
                content.append("配货准备时间：").append(updateShippingDayId).append(";");
            }
            this.update(updateWrapper);
            for (PlatformProductDto platformProductDto : platformProductDtos) {
                operateRecordDos.add(new OperateRecordDo(platformProductDto.getId(), OperateTypeEnum.PlatProduct.getValue(),
                        content.toString(), userId, new Date(), ""));
            }
        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.CrossMall_CMOrder_OperateList, JSON.toJSONString(operateRecordDos));
    }


    private void addCheck(ProductWeightReq req) {
        if ((MathUtils.add(req.getThreeDaysWeight(), req.getSevenDaysWeight(), req.getThirtyDaysWeight())) != 1d) {
            throw new BizException("权重之和不等于1");
        }
    }

    @Override
    public Object addWeight(ProductWeightReq req, Long userId, Long companyId) {
        if (req.getCode() != 1 && (req.getProductIds() == null || req.getProductIds().isEmpty())) {
            return null;
        }
        this.addCheck(req);
        List<PlatformProductDo> asinDoList;
        if (req.getCode() == 1) {
            asinDoList = this.list(new QueryWrapper<PlatformProductDo>().eq("company_id", companyId));
        } else {
            asinDoList = this.list(new QueryWrapper<PlatformProductDo>().in("id", req.getProductIds()));
        }
        if (asinDoList.isEmpty()) {
            return null;
        }
        LambdaUpdateWrapper<PlatformProductDo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(PlatformProductDo::getId, asinDoList.stream().map(PlatformProductDo::getId).collect(Collectors.toList()));
        updateWrapper.set(PlatformProductDo::getThreeDaysWeight, req.getThreeDaysWeight());
        updateWrapper.set(PlatformProductDo::getSevenDaysWeight, req.getSevenDaysWeight());
        updateWrapper.set(PlatformProductDo::getThirtyDaysWeight, req.getThirtyDaysWeight());
        this.update(updateWrapper);
        return "设置成功";
    }


    @Override
    public List<AllocateProductListVo> getAllocatePlanProductListPage(AllocatePlanProductQueryBo bo) {
        return baseMapper.getAllocatePlanProductListPage(bo);
    }
}
